package org.marsdonne.monitring_agent.network

import org.marsdonne.monitring_agent.Reporter

import java.text.SimpleDateFormat

class PingMonitor {
    final static dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    List<String> hosts
    BigDecimal delay = 30.0

    private checkInterval = 18
    private boolean keepRunning = true

    private Reporter reporter

    PingMonitor() {
        Thread.start {
            while (keepRunning) {
                hosts.each { String host ->
                    final String commandText = "ping -c 10 $host"

                    final commander = commandText.execute()

                    switch (commander.waitFor()) {
                        case 0:
                            def commandResult = commander.in.text
                            def result = Parser.parse(commandResult)

                            if(result.lost && new BigDecimal(result.lost) > 0) {
                                reporter.send("[${dateFormatter.format(new Date())}]网络检查命令(Ping)发现丢包，丢失率${result.lost}%", commandResult, "网络检查命令: $commandText")
                            }
                            if(result.max && new BigDecimal(result.max) > delay) {
                                reporter.send("[${dateFormatter.format(new Date())}]网络检查命令(Ping)发现延时，最大耗时${result.max}毫秒", commandResult, "网络检查命令: $commandText")
                            }
                            break
                        default:
                            reporter.send("[${dateFormatter.format(new Date())}]网络检查命令(Ping)执行失败，错误代码:${commander.exitValue()}", commander.err.text, commander.in.text)
                            break
                    }
                }

                sleep checkInterval * 1000
            }
        }
    }

    void stop() {
        keepRunning = false
    }

    static class Parser {
        private final static pattern = ~/PING\b[^(]*\((?<ip>([^)]*))\)\s([^.]*)\..*?|(\d+\sbytes).*?icmp_seq=(\d+).*?ttl=(\d+).*?time=(?<time>(.*))?ms.*?|(?<packets>(\d+))\spackets\stransmitted,\s(\d+)\sreceived,\s(?<lost>(\d+))%\spacket\sloss,\stime\s(?<totalTime>(\d+))ms|rtt\smin\\/avg\\/max\\/mdev\s\=\s(?<min>(\d+.\d+))\\/(?<avg>(\d+.\d+))\\/(?<max>(\d+.\d+))\\/(?<mdev>(\d+.\d+))\sms/

        static Map<String, ?> parse(String content) {
            def result = [:], matcher = pattern.matcher(content)

            while (matcher.find()) {
                result.ip = matcher.group('ip') ?: "--"

                List<Map> details = result.get("details", [])

                def subTime = matcher.group('time')
                if (subTime) {
                    details << [subTime: subTime]
                }

                ["packets", "lost", "totalTime", "min", "avg", "max", "mdev"].each {
                    if (!result.containsKey(it)) {
                        def value = matcher.group(it)
                        if (value) {
                            result[it] = value
                        }
                    }
                }
            }

            result
        }
    }
}
